package com.lanzhou.yuanfen.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lanzhou.yuanfen.cache.ArticleCacheService;
import com.lanzhou.yuanfen.config.Token;
import com.lanzhou.yuanfen.diary.entity.Archive;
import com.lanzhou.yuanfen.diary.entity.Article;
import com.lanzhou.yuanfen.diary.entity.Mood;
import com.lanzhou.yuanfen.diary.service.IArchiveService;
import com.lanzhou.yuanfen.diary.service.IArticleService;
import com.lanzhou.yuanfen.diary.service.IMoodService;
import com.lanzhou.yuanfen.response.ServerResponsePage;
import com.lanzhou.yuanfen.response.ServerResponseResult;
import com.lanzhou.yuanfen.sys.entity.User;
import com.lanzhou.yuanfen.sys.service.IUserService;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created on 2020/5/24 11:12
 * Code By LanZhou
 *
 * @author LanZhou
 */
@RestController
@RequestMapping("/article/")
public class ArticleController {

    @Resource
    private IArticleService articleService;

    @Resource
    private IMoodService iMoodService;

    @Resource
    private IArchiveService iArchiveService;

    @Resource
    private IUserService iUserService;

    @Resource
    private ArticleCacheService articleCacheService;

    /**
     * 获取公开的文章展示文章
     *
     * @return
     */
    @PostMapping("getDisableArticle")
    public ServerResponseResult getDisableArticle() {
        User userInfo = Token.getUserInfo();
        assert userInfo != null;
        Long userKey = userInfo.getUserKey();
        List<Article> articleList = articleService.list(new QueryWrapper<Article>().eq("publicity", true).or(qw -> {
            qw.eq("create_by", userKey);
        }).orderByDesc("update_time", "create_time"));
        setPrivateOrPublic(articleList, userKey);
        return ServerResponseResult.success(articleList);
    }


    /**
     * 获取公开的文章展示文章
     *
     * @return
     */
    @PostMapping("loadArticle")
    public ServerResponseResult loadArticle(@RequestParam("articleKey") Long articleKey) {
        Article article = articleService.getById(articleKey);
        Boolean publicity = article.getPublicity();
        return publicity ? ServerResponseResult.success(article) : ServerResponseResult.fail("当前文章未审核或不存在!");
    }


    /**
     * 添加文章/修改文章
     *
     * @param article
     * @return
     */
    @PostMapping("addOrUpdateArticle")
    public ServerResponseResult addOrUpdateArticle(Article article) {
        article.setUpdateTime(LocalDateTime.now());
        if (StringUtils.isEmpty(article.getArticleKey())) {
            article.setPublicity(false);
            article.setLikes(0);
            article.setViews(0);
            article.setFavorite(0);
        }
        boolean save = articleService.saveOrUpdate(article);
        articleCacheService.insetArticle(article.getArchive(), article.getArticleKey());
        return save ? ServerResponseResult.success() : ServerResponseResult.fail();
    }


    /**
     * 删除文章
     *
     * @param articleKey
     * @return
     */
    @PostMapping("delArticle")
    public ServerResponseResult delArticle(@RequestParam("articleKey") Long articleKey,
                                           @RequestParam("archive") Long archive) {
        boolean save = articleService.removeById(articleKey);
        articleCacheService.removeArticle(archive, articleKey);
        return save ? ServerResponseResult.success() : ServerResponseResult.fail();
    }

    /**
     * 发布文章
     *
     * @param articleKey
     * @return
     */
    @PostMapping("publishArticle")
    public ServerResponseResult publishArticle(@RequestParam("articleKey") Long articleKey) {
        Article article = articleService.getById(articleKey);
        Boolean update = articleCacheService.insetArticle(article.getArchive(), article.getArticleKey());
        if (update) {
            Article publicity = new Article().setArticleKey(articleKey)
                    .setPublicity(true);
            update = articleService.updateById(publicity);
        }
        return update ? ServerResponseResult.success() : ServerResponseResult.fail();
    }


    /**
     * 分页获取文章
     *
     * @param pageSize
     * @param pageIndex
     * @return
     */
    @PostMapping("cacheGetArticle")
    public ServerResponsePage pageGetArticle(@RequestParam("pageSize") Integer pageSize,
                                             @RequestParam("pageIndex") Integer pageIndex,
                                             Long archive,
                                             String sortBy) {

        Map<Long, Set<Long>> setMap = articleCacheService.pageGetArticle(archive, pageIndex, pageSize);
        Iterator<Map.Entry<Long, Set<Long>>> iterator = setMap.entrySet().iterator();
        Map.Entry<Long, Set<Long>> next = iterator.next();
        Long key = next.getKey();
        Set<Long> value = next.getValue();
        List<Article> articles;
        if (value.size() > 0) {
            articles = articleService.list(new QueryWrapper<Article>()
                    .in("article_key", value).orderByDesc(!StringUtils.isEmpty(sortBy), sortBy));
            setRelative(articles);
        } else {
            articles = new ArrayList<>();
        }
        return new ServerResponsePage<>(key, articles);
    }


    /**
     * 分页获取文章
     *
     * @param pageSize
     * @param pageIndex
     * @return
     */
    @PostMapping("pageGetArticle")
    public ServerResponsePage pageGetArticle(@RequestParam("pageSize") Integer pageSize,
                                             @RequestParam("pageIndex") Integer pageIndex) {
        ServerResponsePage<Article> responsePage = new ServerResponsePage<>();
        IPage<Article> iPage = new Page<>(pageIndex, pageSize);
        IPage<Article> page = articleService.page(iPage, new QueryWrapper<Article>()
                .orderByDesc("update_time", "create_time"));
        setRelative(page.getRecords());
        responsePage.setIPage(page);
        return responsePage;
    }


    /**
     * 分页获取文章
     *
     * @param pageSize
     * @param pageIndex
     * @return
     */
    @PostMapping("pageGetPromulgatorArticle")
    public ServerResponsePage pageGetPromulgatorArticle(@RequestParam("pageSize") Integer pageSize,
                                                        @RequestParam("pageIndex") Integer pageIndex,
                                                        @RequestParam("promulgator") String promulgator) {
        ServerResponsePage<Article> responsePage = new ServerResponsePage<>();
        IPage<Article> iPage = new Page<>(pageIndex, pageSize);
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        String[] pros = promulgator.split("mem");
        if (pros.length == 2) {
            wrapper.eq("create_by", pros[1]);
        } else {
            wrapper.eq("create_by", pros[1]);
        }
        IPage<Article> page = articleService.page(iPage, wrapper
                .eq("publicity", Boolean.TRUE)
                .orderByDesc("update_time", "create_time"));
        setRelative(page.getRecords());
        responsePage.setIPage(page);
        return responsePage;
    }

    /**
     * 分页获取文章
     *
     * @param pageSize
     * @param pageIndex
     * @return
     */
    @PostMapping("pageGetMyArticle")
    public ServerResponsePage pageGetMyArticle(@RequestParam("pageSize") Integer pageSize,
                                               @RequestParam("pageIndex") Integer pageIndex,
                                               String sortBy) {
        ServerResponsePage<Article> responsePage = new ServerResponsePage<>();
        IPage<Article> iPage = new Page<>(pageIndex, pageSize);
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        wrapper.eq("create_by", Objects.requireNonNull(Token.getUserInfo()).getUserKey());
        String sortFile = StringUtils.isEmpty(sortBy) ? "create_time" : sortBy;
        IPage<Article> page = articleService.page(iPage, wrapper.orderByDesc(sortFile));
        setRelative(page.getRecords());
        responsePage.setIPage(page);
        return responsePage;
    }


    private void setRelative(List<Article> records) {
        if (records.size() == 0) {
            return;
        }
        List<Mood> moodList = iMoodService.redisCache();
        Map<Long, Mood> moodMap = moodList.stream().collect(Collectors.toMap(Mood::getMoodKey, x -> x));
        List<Archive> archiveList = iArchiveService.redisCache();
        Map<Long, Archive> archiveMap = archiveList.stream().collect(Collectors.toMap(Archive::getArchiveKey, x -> x));
        List<User> userList = iUserService.list();
        Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getUserKey, x -> x));
        for (Article record : records) {
            Long mood = record.getMood();
            Long archive = record.getArchive();
            Long createBy = record.getCreateBy();
            if (mood != null) {
                record.setIMood(moodMap.get(mood));
            }
            if (archive != null) {
                String archiveTxt = "";
                Archive ah = archiveMap.get(archive);
                Long fatherNode = ah.getFatherNode();
                if (fatherNode != null) {
                    Archive father = archiveMap.get(fatherNode);
                    archiveTxt += father.getName() == null ? "" : father.getName();
                }
                archiveTxt += " > " + ah.getName();
                record.setIArchive(archiveTxt);
            }
            if (createBy != null) {
                User byName = userMap.get(createBy);
                if (byName != null) {
                    record.setCreatorName(byName.getNickName());
                    record.setCreatorGender(byName.getGender());
                }
            }
        }
    }


    /**
     * 设置公开的还是私有的
     *
     * @param records
     */
    private void setPrivateOrPublic(List<Article> records, Long userKey) {
        for (Article record : records) {
            if (record.getCreateBy() != null) {
                record.setPublicity(userKey.longValue() == record.getCreateBy().longValue());
            } else {
                record.setPublicity(true);
            }
        }
    }


}
